﻿using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using Plugins;
using Plugins.Core;
using Utils.Wpf;

namespace StockAnalyst2.Plugins.Visualization.Realtime
{
	internal class RealtimePluginViewerVM : ViewModelBase
	{
		#region Attributes

		private readonly NotificationDataSource _dataSource;
		private bool _isVisible;

		#endregion

		#region Properties

		public bool IsVisible
		{
			get
			{
				return _isVisible;
			}
			set
			{
				if (_isVisible != value)
				{
					_isVisible = value;
					base.OnPropertyChanged("IsVisible");
				}
			}
		}

		public ObservableCollection<IStrategyPlugin> Plugins { get; private set; }
		public NotificationViewerVM NotificationViewerVM { get; private set; }

		#endregion

		#region Public Methods

		public RealtimePluginViewerVM(NotificationDataSource dataSource)
		{
			_dataSource = dataSource;
			
			this.Plugins = new ObservableCollection<IStrategyPlugin>();
			this.NotificationViewerVM = new NotificationViewerVM();

			this.Plugins.CollectionChanged += this.Plugins_CollectionChanged; // Local object

			foreach (Notification notification in _dataSource.Load())
			{
				this.NotificationViewerVM.Model.Add(notification);
			}
		}

		#endregion

		#region Event Handlers

		private void Plugins_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
		{
			if (e.Action == NotifyCollectionChangedAction.Add)
			{
				foreach (IStrategyPlugin plugin in e.NewItems)
				{
					plugin.RealtimeNotification += this.Plugin_RealtimeNotification; // Disposed
				}
			}
			else if(e.Action == NotifyCollectionChangedAction.Remove)
			{
				foreach (IStrategyPlugin plugin in e.OldItems)
				{
					plugin.RealtimeNotification -= this.Plugin_RealtimeNotification;
				}
			}
		}

		private void Plugin_RealtimeNotification(object sender, RealtimeNotificationEventArgs e)
		{
			Notification notification = new Notification(DateTime.Now, e.Message);
			this.NotificationViewerVM.Model.Add(notification);
			_dataSource.Save(notification);
		}

		#endregion

		#region IDisposable

		protected bool Disposed { get; private set; }

		private void Dispose(bool disposing)
		{
			if (!this.Disposed)
			{
				this.InternalDispose(disposing);
			}

			this.Disposed = true;
		}

		protected virtual void InternalDispose(bool disposing)
		{
			if (disposing)
			{
				foreach (IStrategyPlugin plugin in this.Plugins)
				{
					plugin.RealtimeNotification -= this.Plugin_RealtimeNotification;
				}
			}

			// Dispose here only unmanaged objects 
			// Don’t use managed objects here because maybe 
			// they have been finalized already
		}

		public void Dispose()
		{
			this.Dispose(true);
			GC.SuppressFinalize(this);
		}

		~RealtimePluginViewerVM()
		{
			this.Dispose(false);
		}

		#endregion
	}
}
